# 进程池
"""
当需要创建的子进程数量不多时，可以直接利用multiprocessing中的Process动态生成多个进程但如果时上百个或者上千个目标。手动创
建进程工作量很大。此时可以用multiprocessing模块的Pool方法。
初始化Pool时，可以指定一个最大进程数，当有新的请求提交到Pool时，如果池没有满，那么就会创建一个新的进程用来执行该请求；但是如
过池中的进程数已经达到最大值，那么该请求就会等待，直到池中的进程结束，才会创建新的进程来执行。

两种类型：
    阻塞式（同步）：添加一个执行一个任务，一个任务不结束，另外一个任务就进不来
    非阻塞式（异步）：和主进程同生共死;　全部添加到队列中，立刻返回，并没有等待其他的进程执行完毕。但是回调函数等待任务结束之后才调用。
进程池:
    pool = Pool(max) 创建进程池对象
    pool.apply() 阻塞的
    pool.apply_async() 非阻塞的

    pool.close() 关闭池
    pool.join() 让主进程让步
"""
import os
from multiprocessing import Pool
import time
from random import random

print("非阻塞式进程".center(30, "*"))


# 非阻塞式进程
def task(task_name):
    print("开始做任务了", task_name)
    start = time.time()
    # 使用sleep
    time.sleep(random() * 2)
    end = time.time()
    # print("完成任务：{}，总耗时：{}，进程ID：{}".format(task_name, (end - start), os.getpid()))
    return "完成任务：{}，总耗时：{}，进程ID：{}".format(task_name, (end - start), os.getpid())


container = []


def callback_func(result):
    """

    :param result:回到返回的对象
    :return:
    """
    # print(result)
    container.append(result)


if __name__ == '__main__':
    # 创建池子
    pool = Pool(5)
    tasks = ["听音乐", "吃饭", "打游戏", "跑步", "看孩子", "散步", "做饭"]
    for tk in tasks:
        pool.apply_async(task, args=(tk,), callback=callback_func)  # 将返回的指给callback_func
    pool.close()  # 添加任务结束
    pool.join()  # 等待左右的完成，在结束主进程

    for contain in container:
        print(contain)
    print("over.......")

print("阻塞式进程".center(30, "*"))
